package com.vpen.service.impl;


import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import com.vpen.model.query.LicenseQuery;
import com.vpen.model.resp.LicenseInfoRespDTO;
import com.vpen.model.resp.LicensePart;
import com.vpen.service.LicenseService;
import com.vpen.utils.CertificateHolder;
import com.vpen.utils.GenerateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URL;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.Objects;
import java.util.Optional;

/**
 * 描述
 *
 * @author 韦鹏
 * @date 2024/11/17 11:21
 */
@Service
public class LicenseServiceImpl implements LicenseService {

    @Autowired
    private CertificateHolder certificateHolder;

    @Override
    public LicenseInfoRespDTO genCode(LicenseQuery query) {
        // 这里只先用自己生成的证书，后面可以支持用提交的证书

        LicenseInfoRespDTO dto = new LicenseInfoRespDTO();
        // 先不处理传参了
        // 生成好的证书写入文件
        GenerateUtil.write2File(certificateHolder.getKeyPair(), certificateHolder.getCertificate());

        String userName = query.getUsername();
        if (StrUtil.isBlank(userName)) {
            userName = "Vpen";
        }
        Date expiryTime = query.getExpiryTime();
        if (Objects.isNull(expiryTime)) {
            LocalDateTime time = LocalDateTimeUtil.now().plusYears(3);
            expiryTime = DateUtil.date(time);
        }
        String expDate = DateUtil.date(expiryTime).toDateStr();
        //构建 power.conf 文件
        String powerConfig = GenerateUtil.buildPowerConfig(certificateHolder);
        // 生成激活码
        String code = GenerateUtil.genLicense(certificateHolder, LicensePart.buildJson(userName, expDate));
        // 还可以把整个打包的目录文件压缩返回给下载
        dto.setCode(code);
        dto.setPowerConfig(powerConfig);
        return dto;
    }

    @Override
    public void genCodeZip(LicenseQuery query) {
        LicenseInfoRespDTO resp = genCode(query);
        String jaPath = StrUtil.join("/", "ja-netfilter");
        String powerConfigPath;
        String activeCodePath;
        URL powerConfigResource = ResourceUtil.getResource(StrUtil.join("/", "ja-netfilter", "config", GenerateUtil.POWER_CONF));
        URL activeCodeResource = ResourceUtil.getResource(StrUtil.join("/", "ja-netfilter", "config", GenerateUtil.ACTIVE_CODE));
        powerConfigPath = powerConfigResource.getPath();
        activeCodePath = activeCodeResource.getPath();
        GenerateUtil.saveFile(powerConfigPath, resp.getPowerConfig());
        GenerateUtil.saveFile(activeCodePath, resp.getCode());
        File zip = ZipUtil.zip(FileUtil.touch(jaPath));
        flushFile(zip);
    }


    private static void flushFile(File file) {
        getResp().ifPresent(response -> {
            try {
                response.setHeader("Content-Disposition", "attachment;filename=" + java.net.URLEncoder.encode(file.getName(), "UTF-8"));
                response.setContentType("application/octet-stream");
                try (FileInputStream fis = new FileInputStream(file)) {
                    IoUtil.copy(fis, response.getOutputStream());
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        });
    }


    private static Optional<HttpServletResponse> getResp() {
        // 获取当前请求的 ServletRequestAttributes

        return Optional.ofNullable(getServletRequestAttributes().getResponse());
    }

    private static ServletRequestAttributes getServletRequestAttributes() {
        return (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    }
}
